<template>
	<div class="wordsDetailBox">
		<AppHeader title="单词跟读练习" :banAnimate="true" backgroundColor="#FFFFFF" titleColor="#000"
			@leftClickEvent="handleHeaderLeft()"></AppHeader>
		<div class="wordBox">
			<div class="progressBox">
				<div> <span class="active">{{(currentIndex+1)}}</span>/{{brushWordsList.length}}</div>
				<div class="progress">
					<div class="current" :style="{width:((currentIndex+1)/brushWordsList.length)*100+'%'}"></div>
				</div>
			</div>
			<div class="image" v-if="wordsDetail.wordsjson.wordPic">
				<img :src="wordsDetail.wordsjson.wordPic" />
			</div>
			<div class="words">{{wordsDetail.wordsjson.words}}</div>
			<div class="phoneticSymbol" v-if="wordsDetail.wordsjson.symbol">[{{wordsDetail.wordsjson.symbol}}]
			</div>
			<div class="explain">{{wordsDetail.wordsjson.pretations}}</div>
			<div class="title" v-if="wordsDetail.wordsjson.sentences">例句</div>
			<div class="exampleEn">{{wordsDetail.wordsjson.sentences}}</div>
			<!-- <div class="exampleZh">我是两天前来这儿的</div> -->
		</div>
		<div class="practiceFractionBox">
			<div class="practiceFraction" v-if="recordingStatus=='ended'&&wordsDetail.sourceObj">
				<div :class="autoColor(wordsDetail.sourceObj.total_score)">
					{{Math.round(wordsDetail.sourceObj.total_score)}}分
				</div>
				<img src="@/assets/images/brushWords/scoreSrcRed.png"
					v-if="wordsDetail.sourceObj.total_score<60&&recordingStatus=='ended'" />
				<img src="@/assets/images/brushWords/scoreSrcYellow.png"
					v-if="(wordsDetail.sourceObj.total_score>=60&&wordsDetail.sourceObj.total_score<=80)&&recordingStatus=='ended'" />
				<img src="@/assets/images/brushWords/scoreSrcGreed.png"
					v-if="wordsDetail.sourceObj.total_score>80&&recordingStatus=='ended'" />
				<div class="context">
					<div class="label">完成度</div>
					<div :class="autoColor(wordsDetail.sourceObj.integrity_score)">
						{{Math.round(wordsDetail.sourceObj.integrity_score) }}
					</div>
				</div>
				<div class="context">
					<div class="label">流利度</div>
					<div :class="autoColor(wordsDetail.sourceObj.fluency_score)">
						{{Math.round(wordsDetail.sourceObj.fluency_score) }}
					</div>
				</div>
				<div class="context">
					<div class="label">准确度</div>
					<div :class="autoColor(wordsDetail.sourceObj.accuracy_score)">
						{{Math.round(wordsDetail.sourceObj.accuracy_score)}}
					</div>
				</div>
			</div>
		</div>
		<div class="practiceButton" v-if="recordingStatus!='ended'">
			<view class="wordsVoice" v-if="wordsDetail.wordFile">
				<!-- 		<img src="@/assets/images/brushWords/voice.png" v-if="!isPlayWords" @click="playAudio()" />
				<img src="@/assets/images/brushWords/microphone.gif" v-else /> -->
			</view>
			<!-- 弹性盒占位 -->
			<div class="wordsVoice" v-else></div>
			<view class="wordsPlay">
				<!-- @click="tapeClick" -->
				<div class="circle-container" v-if="recordingStatus=='recording'">
					<van-circle class="van-circle" :current-rate="currentRate" start-position="top" color="#0cb76c"
						size="70" />
					<img src="@/assets/images/brushWords/isRecording.gif" style="position: absolute;" />
				</div>
				<img src="@/assets/images/brushWords/recording.gif"
					v-if="wordsDetail.id&&recordingStatus=='notStarted'" />
			</view>
			<view class="myVoice">
				<!-- <img src="@/assets/images/brushWords/play.png" @click="playRecording" v-if="recordingStatus=='ended'" />
				<div @click="completeClick" class="complete" v-if="recordingStatus=='recording'">完成录音</div> -->
			</view>
		</div>
		<!-- 填充盒子 -->
		<div class="fillBox"></div>
		<div class="practiceBottom" v-if="recordingStatus=='ended'">
			<div @click="againRead" class="again">重读</div>
			<div @click="nextWords" class="next">{{(currentIndex+1)==brushWordsList.length?'完成':'下一个'}}</div>
		</div>
		<van-overlay :show="recordingStatus=='evaluating'">
			<div class="loading">
				<van-loading type="spinner" />
				<div class="text">评分中...</div>
			</div>
		</van-overlay>
		<audio ref="audioElement" :src="audioSrc" @ended="playEnded"></audio>
		<audio ref="dingAudioElement" :src="dingAudioSrc" @ended="dingPlayEnded"></audio>
	</div>
</template>

<script setup>
	import AppHeader from "@/components/AppHeader.vue";
	import {
		ref,
		watch,
		reactive,
		nextTick,
		onMounted,
		onUnmounted
	} from "vue";
	import {
		showToast,
	} from "vant";
	import IatRecorder from '@/utils/iatRecorder'

	import {
		useRouter,
		useRoute
	} from "vue-router";
	const route = useRoute();
	const router = useRouter();
	//返回上一页
	const handleHeaderLeft = () => {
		router.go(-1);
	};

	const audioElement = ref(null)
	let recordedChunks = [];
	let iatRecorder = new IatRecorder();
	let mediaRecorder;

	const currentIndex = ref(0) //当前单词索引
	const brushWordsList = ref([]) //练习单词列表
	const wordsDetail = ref({
		wordsjson: {}
	}) //单词详情信息
	//和获取单词详情信息
	import {
		saveWordsRecord,
		getWordsInfo,
		uploadFiles
	} from "@/api/brushWords.js";


	const recordingStatus = ref('notStarted') //录音状态 notStarted未开始  recording 录音中 ended 已结束 evaluating评测中
	const audioSrc = ref('') //音频资源文件
	const recordedSrc = ref('') //个人录音文件

	const isPlayWords = ref(false) //是否正在播放单词
	const currentRate = ref(0); //圆形当前数值
	const rateTimeVal = ref(null); //圆形当前数值
	watch(currentIndex, (newVal) => {
		if (wordsDetail.value) {
			iatRecorder = new IatRecorder({
				text: wordsDetail.value.wordsjson.words
			})
		}
	}, {
		immediate: true
	})
	const setRateInterval = (time) => {
		currentRate.value = 0;
		clearInterval(rateTimeVal.value);
		const stepTime = (100 / time) / 4;
		rateTimeVal.value = setInterval(() => {
			currentRate.value += stepTime;
			if (currentRate.value >= 100) {
				setTimeout(() => {
					currentRate.value = 0
				}, 200)
				clearInterval(rateTimeVal.value);
			}
		}, 250);
	};
	// 重读
	const againRead = () => {
		wordsDetail.value.sourceObj = ''
		recordingStatus.value = 'notStarted'
		playAudio()
		// tapeClick()
	}

	//下一个单词
	const nextWords = () => {
		if (wordsDetail.value.wordsjson.video == '') {
			return showToast('请先朗读单词')
		}

		if ((currentIndex.value + 1) == brushWordsList.value.length) {
			if (route.query.type == 'detail') {
				return router.go(-1);
			}
			if (route.query.type == 'practice') {
				return router.go(-2);
			}
		}
		currentIndex.value++
		recordedChunks = []
		recordingStatus.value = 'notStarted'
		getWordsDetail()

	}

	// 播放音频
	const playAudio = (type) => {
		audioSrc.value = wordsDetail.value.wordsjson.wordFile
		isPlayWords.value = true
		setTimeout(async () => {
			await audioElement.value.play()
		}, 1000)

	}
	//播放结束
	const playEnded = async () => {
		isPlayWords.value = false
		tapeClick()
	}

	const videoTimeoutVal = ref()
	const dingAudioSrc = ref(null)
	const dingAudioElement = ref(null)
	const dingPlayEnded = async () => {
		clearTimeout(videoTimeoutVal.value)
		recordingStatus.value = 'recording'
		startRecording() //开始录音
		iatRecorder.start()
		setRateInterval(5)
		videoTimeoutVal.value = setTimeout(async () => {
			recordingStatus.value = 'evaluating'
			completeClick()
		}, 5000);
	}

	//语音识别
	const tapeClick = () => {
		dingAudioSrc.value = "https://oss.bigchun.com/file/ding.mp3"
		dingAudioElement.value.play().catch((err) => {
			dingAudioElement.value.play()
		})
	}
	const sourceTimeoutVal = ref()
	const completeTimeoutVal = ref()
	//完成识别
	const completeClick = async () => {
		clearTimeout(videoTimeoutVal.value)

		iatRecorder.stop()
		stopRecording() //结束录音
		completeTimeoutVal.value = setTimeout(async () => {
			recordingStatus.value = 'ended'
			if (iatRecorder.getScoreObj()) {
				wordsDetail.value.sourceObj = iatRecorder.getScoreObj()
				if (wordsDetail.value.sourceObj.total_score == 0) {
					sourceTimeoutVal.value = setTimeout(() => {
						againRead()
					}, 1000)
					return showToast('请提高朗读音量,以免影响评分')
				}
				if (wordsDetail.value.score < wordsDetail.value.sourceObj.total_score) {
					const blob = new Blob(recordedChunks, {
						type: mediaRecorder.mimeType
					});
					var file = new File([blob], wordsDetail.value.wordsjson.words + '.MP3', {
						type: 'audio/x-mpeg',
						lastModified: Date.now()
					});
					let formData = new FormData();
					formData.append('file', file);
					uploadFiles(formData).then(res => {
						wordsDetail.value.video = res.data.url
						wordsDetail.value.fullVideo = res.data.fullurl
						saveWords()
					})
				} else {
					wordsDetail.value.video = wordsDetail.value.myvideosource
					saveWords()
				}
			} else {
				showToast('录音解析失败')
				wordsDetail.value.sourceObj = null
			}
		}, 2000);
	}

	const startRecording = async () => {
		try {
			recordedChunks = []
			const stream = await navigator.mediaDevices.getUserMedia({
				audio: true
			});
			mediaRecorder = new MediaRecorder(stream);
			mediaRecorder.addEventListener('dataavailable', event => {
				console.log("录音数据", event.data)
				recordedChunks.push(event.data);
			});
			mediaRecorder.start();
		} catch (error) {
			console.error('获取媒体流错误:', error);
		}
	};

	const stopRecording = async () => {
		wordsDetail.value.recordedChunks = recordedChunks
		if (mediaRecorder) {
			mediaRecorder.stop();
		}
	};

	const saveWords = () => {
		saveWordsRecord({
			id: brushWordsList.value[currentIndex.value],
			score: Math.round(wordsDetail.value.sourceObj.total_score),
			myvideosource: wordsDetail.value.video || ''
		}).then(res => {

		})
	};

	const blobToBase64 = (blob) => {
		return new Promise((resolve, reject) => {
			const reader = new FileReader();
			reader.readAsDataURL(blob);
			reader.onload = () => resolve(reader.result);
			reader.onerror = reject;
		});
	};

	const getWordsDetail = () => {
		getWordsInfo({
			id: brushWordsList.value[currentIndex.value]
		}).then(res => {
			wordsDetail.value = res.data
			iatRecorder = new IatRecorder({
				text: wordsDetail.value.wordsjson.words
			})
			playAudio()
		})
	}

	//自动化颜色
	const autoColor = (num) => {
		if (num < 60) {
			return 'autoRed' //#FA192C
		} else if (num >= 60 && num <= 80) {
			return 'autoYellow' //#FF9917
		} else if (num > 80) {
			return 'autoGreed' //#0CB76C
		}
	}

	onMounted(() => {
		let brushWords = localStorage.getItem("brushWordsSelect")
		brushWordsList.value = JSON.parse(brushWords)
		//获取单词详情信息
		getWordsDetail()

	})
	onUnmounted(() => {
		if (mediaRecorder) {
			stopRecording() //结束录音
		}
		if (iatRecorder) {
			iatRecorder.stop()
		}
		clearTimeout(videoTimeoutVal.value)
		clearTimeout(sourceTimeoutVal.value)
		clearTimeout(completeTimeoutVal.value)
	})
</script>

<style lang="scss" scoped>
	.loading {
		display: flex;
		align-items: center;
		justify-content: center;
		color: #ffffff;
		height: 100%;
		font-size: 18px;

		.text {
			margin-left: 10px;
		}
	}

	.circle-container {
		width: 70px;
		/* 容器大小，根据需要调整 */
		height: 70px;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.circle-progress {
		width: 100%;
		height: 100%;
	}

	.circle-bg {
		stroke: #FFFFFF;
		/* 背景圆线条颜色 */
	}

	.circle {
		/* 动画定义 */
		animation: progress 5s ease-out forwards;
	}

	@keyframes progress {
		0% {
			stroke-dashoffset: 100.48;
			/* 初始时，线条完全不可见 */
		}

		100% {
			stroke-dashoffset: 0;
			/* 结束时，线条完全可见 */
		}
	}

	.fillBox {
		height: 40px;
	}

	.practiceBottom {
		position: fixed;
		width: 100%;
		bottom: 0;
		height: 28px;
		background: #E7F8F0;
		color: #0CB76C;
		font-size: 12px;
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 0 20px;
		box-sizing: border-box;

		.again,
		.next {
			width: 80px;
			height: 22px;
			line-height: 22px;
			text-align: center;
			border-radius: 18px;
			border: 1px solid #0CB76C;
		}
	}

	.practiceFractionBox {
		display: flex;
		align-items: center;
		justify-content: flex-end;
		padding: 0 20px;

		.practiceFraction {
			display: inline-block;
			font-size: 28px;

			img {
				width: 55px;
				height: 12px;
				margin-bottom: 6px;
			}

			.context {
				margin-top: 5px;
				display: flex;
				align-items: center;
				color: #8E8E8E;
				font-size: 12px;

				.lebel {
					margin-right: 6px;
				}
			}
		}
	}


	.practiceButton {
		height: 52px;
		margin-top: 10px;
		display: flex;
		justify-content: center;
		align-items: center;
		padding: 0 20px 20px;
		position: fixed;
		width: 100%;
		bottom: 28px;
		box-sizing: border-box;
		background-color: #FFFFFF;

		.wordsVoice {
			flex: 1;
			text-align: center;

			img {
				width: 26px;
				height: 20px;
			}
		}

		.wordsPlay {
			flex: 1;
			text-align: center;
			display: flex;
			justify-content: center;

			img {
				width: 52px;
				height: 52px;
			}
		}

		.myVoice {
			flex: 1;
			text-align: center;

			img {
				width: 26px;
				height: 26px;
			}
		}

		.complete {
			font-size: 16px;
			color: #0CB76C;
		}
	}

	.wordsDetailBox {
		width: 100%;
		height: 100%;
		background-color: #FFFFFF;
		overflow: scroll;

		.wordBox {
			padding: 54px 10px 15px;
			display: flex;
			flex-direction: column;

			.progressBox {
				display: flex;
				align-items: center;
				font-size: 16px;
				color: #8E8E8E;

				.active {
					color: #0CB76C;
				}

				.progress {
					flex: 1;
					margin-left: 13px;
					height: 2px;
					background: #E5E5E5;
					border-radius: 1px;
					position: relative;
				}

				.current {
					position: absolute;
					top: 0;
					left: 0;
					height: 2px;
					background: #0CB76C;
					border-radius: 1px;
				}
			}

			.words {
				text-align: center;
				font-size: 32px;
				font-weight: bold;
				color: #333333;
				margin-top: 20px;
			}

			.phoneticSymbol {
				margin-top: 10px;
				text-align: center;
				font-size: 18px;
				color: #8E8E8E;
			}

			.explain {
				margin-top: 10px;
				text-align: center;
				font-size: 14px;
				color: #8E8E8E;
			}

			.title {
				margin-top: 20px;
				text-align: center;
				font-size: 14px;
				color: #8E8E8E;
			}

			.image {
				width: 320px;
				height: 180px;
				margin: 30px auto 0px;
				background: #D8D8D8;
				border-radius: 10px;

				img {
					width: 100%;
					height: 100%;
				}
			}

			.exampleEn,
			.exampleZh {
				text-align: center;
				font-size: 14px;
				color: #8E8E8E;
				margin-top: 10px;
			}
		}
	}

	.autoRed {
		color: #FA192C !important;
	}

	.autoYellow {
		color: #FF9917 !important;
	}

	.autoGreed {
		color: #0CB76C !important;
	}
</style>